<template>
  <view class="content">
    <!-- AI对话区域 -->
    <view class="response-container">
      <!-- 对话头部 -->
      <view class="response-header">
        <text class="response-title">AI 对话</text>
        <text class="response-count" v-if="conversations.length > 0">共 {{ conversations.length }} 轮对话</text>
      </view>
      
      <!-- 滚动聊天区域 -->
      <scroll-view 
        scroll-y 
        class="response-area" 
        :scroll-top="scrollTop" 
        @scroll="onScroll"
        :scroll-with-animation="true"
        scroll-anchoring="true"
      >
        <view class="conversation-list">
          <!-- 对话历史列表 -->
          <view class="conversation-item" v-for="(conversation, index) in conversations" :key="index">
            <!-- 用户问题消息框 -->
            <view class="user-message">
              <view class="message-header">
                <text class="message-role">用户问题</text>
                <text class="message-number">#{{ index + 1 }}</text>
              </view>
              <view class="message-content">{{ conversation.question }}</view>
            </view>
            
            <!-- AI回答消息框 -->
            <view class="ai-message">
              <view class="message-header">
                <text class="message-role">AI回答</text>
                <text class="message-status" v-if="index === conversations.length - 1 && isConnected">正在回复...</text>
              </view>
              <view class="message-content">{{ conversation.answer }}</view>
            </view>
          </view>
          
          <!-- 底部占位，确保滚动空间 -->
          <view class="scroll-placeholder" style="height: 100rpx;"></view>
        </view>
      </scroll-view>
      
      <!-- 滚动到底部按钮 -->
      <view class="scroll-to-bottom-btn" v-if="conversations.length > 0 && !isAtBottom" @click="forceScrollToBottom">
        <text class="btn-icon">↓</text>
      </view>
    </view>

    <!-- 用户输入区域 -->
    <view class="input-area">
      <textarea 
        v-model="userQuery" 
        placeholder="请输入您的问题" 
        class="query-input"
        :disabled="isConnected"
      />
    </view>

    <!-- 操作按钮区域 -->
    <view class="btn-area">
      <button class="btn" @click="startStream" :disabled="isConnected || !userQuery.trim()">发送问题</button>
      <button class="btn btn-stop" @click="stopStream" v-if="isConnected">停止响应</button>
      <button class="btn btn-clear" @click="clearMessages" v-if="conversations.length > 0">清空对话</button>
    </view>

    <!-- 状态显示区域 -->
    <view class="status-area">
      <text class="status">{{ statusMessage }}</text>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue'

// ==================== 响应式数据定义 ====================
const conversations = ref([])           // 对话历史记录 [{ question: '', answer: '' }]
const statusMessage = ref('准备就绪')   // 状态消息显示
const isConnected = ref(false)          // SSE连接状态
const scrollTop = ref(0)                // 滚动位置控制
const baseApiUrl = ref('http://localhost') // API基础地址
const userQuery = ref('')               // 用户输入的问题
const apiKey = ref('app-wcpS7Lnfdkp1UNQEscTt8oV1') // API密钥
const controller = ref(null)            // 请求控制器，用于中断请求
const conversationId = ref('')          // 对话ID，维持上下文连续性

// 滚动相关状态
const isAtBottom = ref(true)            // 是否在底部位置
const scrollIncrementCounter = ref(0)   // 滚动计数器，强制触发滚动更新

// ==================== 初始化配置 ====================
onMounted(() => {
  // 根据不同平台配置API地址
  // #ifdef H5
  baseApiUrl.value = 'http://localhost'
  // #endif
  
  // #ifdef APP-PLUS
  const systemInfo = uni.getSystemInfoSync()
  if (systemInfo.platform === 'ios') {
    baseApiUrl.value = 'http://localhost'
  } else {
    baseApiUrl.value = 'http://10.0.2.2' // Android模拟器地址
  }
  // #endif
})

// ==================== 工具函数 ====================
/**
 * 更新状态消息
 */
const updateStatus = (msg) => {
  statusMessage.value = msg
}

/**
 * 滚动事件处理 - 检测是否在底部
 */
const onScroll = (e) => {
  const { scrollTop: currentScrollTop, scrollHeight, height } = e.detail
  const bottomThreshold = 50 // 底部阈值（rpx）
  const distanceFromBottom = scrollHeight - currentScrollTop - height
  isAtBottom.value = distanceFromBottom < bottomThreshold
}

/**
 * 滚动到底部
 * 使用计数器确保每次滚动值都不同，强制触发更新
 */
const scrollToBottom = () => {
  nextTick(() => {
    scrollIncrementCounter.value++
    // 设置一个很大的值确保滚动到最底部
    scrollTop.value = 999999 + scrollIncrementCounter.value
    
    // 延迟更新底部状态
    setTimeout(() => {
      isAtBottom.value = true
    }, 200)
  })
}

/**
 * 手动点击滚动到底部
 */
const forceScrollToBottom = () => {
  scrollToBottom()
}

// ==================== 对话管理 ====================
/**
 * 清空所有对话记录
 */
const clearMessages = () => {
  conversations.value = []
  conversationId.value = ''
  scrollIncrementCounter.value = 0
  updateStatus('对话已清空')
}

/**
 * 开始新的AI对话请求
 */
const startStream = () => {
  // 检查状态：不能在连接中或输入为空时发送
  if (isConnected.value || !userQuery.value.trim()) return
  
  // 保存用户问题
  const currentQuestion = userQuery.value.trim()
  
  // 添加新的对话记录到历史中
  conversations.value.push({
    question: currentQuestion,
    answer: ''
  })
  
  // 清空输入框
  userQuery.value = ''
  updateStatus('正在请求AI...')
  
  // 停止之前可能存在的连接
  stopConnection()
  
  // 延迟发送请求，确保UI更新完成
  setTimeout(() => {
    const requestData = {
      inputs: {},
      query: currentQuestion,
      response_mode: "streaming",
      conversation_id: conversationId.value, // 保持对话上下文
      user: "user-cao"
    }
    
    // 创建新的请求控制器
    controller.value = new AbortController()
    fetchSSE(requestData)
    
    // 立即滚动到新问题位置
    setTimeout(() => {
      scrollToBottom()
    }, 100)
  }, 300)
}

// ==================== SSE连接处理 ====================
/**
 * 使用Fetch API处理Server-Sent Events
 */
const fetchSSE = (requestData) => {
  const url = `${baseApiUrl.value}/v1/chat-messages`
  
  fetch(url, {
    method: 'POST',
    headers: {
      'Accept': 'text/event-stream',
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${apiKey.value}`
    },
    body: JSON.stringify(requestData),
    signal: controller.value.signal
  })
  .then(response => {
    // 检查响应状态
    if (!response.ok) {
      throw new Error(`HTTP错误: ${response.status} ${response.statusText}`)
    }
    
    isConnected.value = true
    updateStatus('连接已建立')
    
    // 开始处理流式响应
    return processStream(response)
  })
  .catch(error => {
    // 处理请求错误
    if (error.name === 'AbortError') {
      updateStatus('请求已停止')
      return
    }
    
    console.error('连接错误:', error)
    updateStatus('连接错误: ' + (error.message || '未知错误'))
    
    // 移除失败的空对话记录
    if (conversations.value.length > 0 && conversations.value[conversations.value.length - 1].answer === '') {
      conversations.value.pop()
    }
    
    isConnected.value = false
  })
}

/**
 * 处理流式响应数据
 */
const processStream = async (response) => {
  const reader = response.body.getReader()
  const decoder = new TextDecoder()
  let buffer = '' // 缓冲区，处理不完整的数据块
  
  while (true) {
    const { value, done } = await reader.read()
    
    // 流读取完成
    if (done) {
      isConnected.value = false
      updateStatus('AI响应完成')
      return
    }
    
    // 解码数据块并添加到缓冲区
    const chunk = decoder.decode(value, { stream: true })
    buffer += chunk
    
    // 处理缓冲区中的完整SSE消息
    while (true) {
      // 查找消息结束标志（两个换行符）
      const endIndex = buffer.indexOf('\n\n')
      if (endIndex === -1) break
      
      // 提取完整消息
      const message = buffer.substring(0, endIndex).trim()
      buffer = buffer.substring(endIndex + 2)
      
      // 处理非空消息
      if (message) {
        processSSEMessage(message)
      }
    }
  }
}

/**
 * 处理单个SSE消息
 * AI每次输出内容都会触发此函数，实现实时滚动
 */
const processSSEMessage = (rawMessage) => {
  // 提取JSON数据（格式：data: {...}）
  const dataMatch = rawMessage.match(/^data: ({.*})$/m)
  
  if (dataMatch && dataMatch[1]) {
    try {
      const jsonData = JSON.parse(dataMatch[1])
      const eventType = jsonData.event
      
      if (eventType === 'message' || eventType === 'agent_message') {
        // AI内容消息
        const chunk = jsonData.answer || ''
        
        // 追加到最新对话的答案中
        if (conversations.value.length > 0) {
          const lastConversation = conversations.value[conversations.value.length - 1]
          lastConversation.answer += chunk
        }
        
        // 保存对话ID以维持上下文
        if (jsonData.conversation_id) {
          conversationId.value = jsonData.conversation_id
        }
        
        // 立即滚动到底部，跟随AI输出
        scrollToBottom()
        updateStatus('正在接收AI响应...')
      }
      else if (eventType === 'message_end') {
        // 消息结束
        updateStatus('AI响应完成')
        if (jsonData.conversation_id) {
          conversationId.value = jsonData.conversation_id
        }
        // 确保最后滚动到底部
        scrollToBottom()
      }
      else if (eventType === 'tts_message') {
        // TTS消息（文本转语音）
        updateStatus('收到TTS消息')
      }
    } catch (parseError) {
      // JSON解析失败，直接添加原始消息
      console.error('JSON解析失败:', parseError)
      
      if (conversations.value.length > 0) {
        const lastConversation = conversations.value[conversations.value.length - 1]
        lastConversation.answer += rawMessage
      }
      scrollToBottom()
    }
  } else {
    // 无法识别的消息格式，直接添加
    if (conversations.value.length > 0) {
      const lastConversation = conversations.value[conversations.value.length - 1]
      lastConversation.answer += rawMessage
    }
    scrollToBottom()
  }
}

// ==================== 连接控制 ====================
/**
 * 停止当前AI响应
 */
const stopStream = () => {
  updateStatus('正在停止响应...')
  stopConnection()
}

/**
 * 终止SSE连接
 */
const stopConnection = () => {
  if (controller.value) {
    controller.value.abort()
    controller.value = null
  }
  
  isConnected.value = false
  updateStatus('连接已停止')
}
</script>

<style lang="scss" scoped>
/* ==================== 全局样式重置 ==================== */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}

/* ==================== 主容器 ==================== */
.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20rpx;
  width: 100%;
  background-color: #f8f9fa;
  min-height: 100vh;
}

/* ==================== 对话区域 ==================== */
.response-container {
  width: 100%;
  max-width: 700rpx;
  margin: 20rpx 0;
  border-radius: 16rpx;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  overflow: hidden;
  background: #ffffff;
  position: relative;

  .response-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20rpx 24rpx;
    background-color: #4a6cf7;

    .response-title {
      font-size: 32rpx;
      font-weight: 600;
      color: #ffffff;
    }

    .response-count {
      font-size: 26rpx;
      color: rgba(255, 255, 255, 0.8);
    }
  }

  .response-area {
    width: 100%;
    padding: 30rpx;
    min-height: 800rpx;
    max-height: 1000rpx;
    background-color: #ffffff;
  }
}

/* ==================== 对话列表 ==================== */
.conversation-list {
  display: flex;
  flex-direction: column;
  gap: 40rpx;
  padding-bottom: 40rpx;
}

.conversation-item {
  display: flex;
  flex-direction: column;
  gap: 20rpx;
  padding-bottom: 40rpx;
  border-bottom: 1rpx solid #e9ecef;

  &:last-child {
    border-bottom: none;
    padding-bottom: 20rpx;
  }
}

/* ==================== 消息样式 ==================== */
.user-message, .ai-message {
  padding: 24rpx;
  border-radius: 12rpx;
  animation: fadeIn 0.3s ease;
  margin: 0 20rpx;
}

.user-message {
  background-color: #e3f2fd;
  border-left: 4rpx solid #2196f3;
  margin-right: 60rpx; /* 右侧留空间 */
}

.ai-message {
  background-color: #f0f4ff;
  border-left: 4rpx solid #4a6cf7;
  margin-left: 60rpx; /* 左侧留空间 */
}

.message-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16rpx;

  .message-role {
    font-size: 24rpx;
    font-weight: 600;
    color: #6c757d;
  }

  .message-number, .message-status {
    font-size: 22rpx;
    color: #6c757d;
    background: rgba(255, 255, 255, 0.7);
    padding: 4rpx 12rpx;
    border-radius: 12rpx;
  }

  .message-status {
    color: #4a6cf7;
    animation: pulse 1.5s infinite;
  }
}

.message-content {
  font-size: 30rpx;
  color: #333333;
  line-height: 1.8;
  word-wrap: break-word;
  padding: 8rpx 0;
}

/* ==================== 动画效果 ==================== */
@keyframes pulse {
  0%, 100% { 
    opacity: 1; 
  }
  50% { 
    opacity: 0.5; 
  }
}

@keyframes fadeIn {
  from { 
    opacity: 0; 
    transform: translateY(20rpx); 
  }
  to { 
    opacity: 1; 
    transform: translateY(0); 
  }
}

/* ==================== 滚动按钮 ==================== */
.scroll-to-bottom-btn {
  position: absolute;
  bottom: 20rpx;
  right: 20rpx;
  width: 80rpx;
  height: 80rpx;
  background-color: #4a6cf7;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4rpx 16rpx rgba(74, 108, 247, 0.3);
  cursor: pointer;
  transition: all 0.3s ease;
  z-index: 10;

  &:hover {
    background-color: #3956d4;
    transform: scale(1.1);
  }

  &:active {
    transform: scale(0.95);
  }

  .btn-icon {
    font-size: 36rpx;
    color: #ffffff;
    font-weight: bold;
  }
}

/* ==================== 输入区域 ==================== */
.input-area {
  width: 100%;
  max-width: 700rpx;
  margin: 20rpx 0;

  .query-input {
    width: 100%;
    height: 160rpx;
    padding: 24rpx;
    border: 1rpx solid #ced4da;
    border-radius: 16rpx;
    font-size: 30rpx;
    background: #ffffff;
    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  }
}

/* ==================== 按钮区域 ==================== */
.btn-area {
  display: flex;
  gap: 20rpx;
  width: 100%;
  max-width: 700rpx;
  margin: 20rpx 0;

  .btn {
    flex: 1;
    background-color: #4a6cf7;
    color: #ffffff;
    border-radius: 12rpx;
    padding: 20rpx 0;
    font-size: 30rpx;
    border: none;
    transition: all 0.2s;

    &:active {
      transform: scale(0.98);
      opacity: 0.9;
    }

    &:disabled {
      opacity: 0.6;
      cursor: not-allowed;
    }

    &.btn-stop {
      background-color: #ff6b6b;
    }

    &.btn-clear {
      background-color: #6c757d;
    }
  }
}

/* ==================== 状态区域 ==================== */
.status-area {
  width: 100%;
  max-width: 700rpx;
  padding: 16rpx;
  text-align: center;
  background-color: #e9ecef;
  border-radius: 12rpx;
  margin-top: 10rpx;

  .status {
    font-size: 26rpx;
    color: #495057;
    font-weight: 500;
  }
}

/* ==================== 响应式设计 ==================== */
@media screen and (max-width: 768px) {
  .response-container,
  .input-area,
  .btn-area,
  .status-area {
    max-width: 95%;
  }

  .response-area {
    max-height: 800rpx;
  }

  .user-message {
    margin-right: 40rpx;
  }

  .ai-message {
    margin-left: 40rpx;
  }

  .scroll-to-bottom-btn {
    width: 60rpx;
    height: 60rpx;
    bottom: 15rpx;
    right: 15rpx;

    .btn-icon {
      font-size: 28rpx;
    }
  }
}
</style>